home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_300 / 365_01 / elvprsv.c < prev    next >
C/C++ Source or Header  |  1992-04-04  |  7KB  |  287 lines

  1. /* elvprsv.c */
  2.  
  3. /* Author:
  4.  *    Steve Kirkendall
  5.  *    14407 SW Teal Blvd. #C
  6.  *    Beaverton, OR 97005
  7.  *    kirkenda@cs.pdx.edu
  8.  */
  9.  
  10.  
  11. /* This file contains the portable sources for the "elvprsv" program.
  12.  * "Elvprsv" is run by Elvis when Elvis is about to die.  It is also
  13.  * run when the computer boots up.  It is not intended to be run directly
  14.  * by the user, ever.
  15.  *
  16.  * Basically, this program does the following four things:
  17.  *    - It extracts the text from the temporary file, and places the text in
  18.  *    a file in the /usr/preserve directory.
  19.  *    - It adds a line to the /usr/preserve/Index file, describing the file
  20.  *    that it just preserved.
  21.  *    - It removes the temporary file.
  22.  *    -    It sends mail to the owner of the file, saying that the file was
  23.  *    preserved, and how it can be recovered.
  24.  *
  25.  * The /usr/preserve/Index file is a log file that contains one line for each
  26.  * file that has ever been preserved.  Each line of this file describes one
  27.  * preserved file.  The first word on the line is the name of the file that
  28.  * contains the preserved text.  The second word is the full pathname of the
  29.  * file that was being edited; for anonymous buffers, this is the directory
  30.  * name plus "/foo".
  31.  *
  32.  * If elvprsv's first argument (after the command name) starts with a hyphen,
  33.  * then the characters after the hyphen are used as a description of when
  34.  * the editor went away.  This is optional.
  35.  *
  36.  * The remaining arguments are all the names of temporary files that are
  37.  * to be preserved.  For example, on a UNIX system, the /etc/rc file might
  38.  * invoke it this way:
  39.  *
  40.  *    elvprsv "-the system went down" /tmp/elv_*.*
  41.  *
  42.  * This file contains only the portable parts of the preserve program.
  43.  * It must #include a system-specific file.  The system-specific file is
  44.  * expected to define the following functions:
  45.  *
  46.  *    char *ownername(char *filename)    - returns name of person who owns file
  47.  *
  48.  *    void mail(char *user, char *name, char *when)
  49.  *                    - tell user that file was preserved
  50.  */
  51.  
  52. #include <stdio.h>
  53. #include "config.h"
  54. #include "vi.h"
  55.  
  56. #if AMIGA
  57. BLK tmpblk;
  58. # include "amiwild.c"
  59. # include "amiprsv.c"
  60. #endif
  61.  
  62. #if OSK
  63. # undef sprintf
  64. #endif
  65.  
  66. #if ANY_UNIX || OSK
  67. # include "prsvunix.c"
  68. #endif
  69.  
  70. #if MSDOS || TOS
  71. # include "prsvdos.c"
  72. # define WILDCARD_NO_MAIN
  73. # include "wildcard.c"
  74. #endif
  75.  
  76.  
  77. BLK    buf;
  78. BLK    hdr;
  79. BLK    name;
  80. int    rewrite_now;    /* boolean: should we send text directly to orig file? */
  81.  
  82.  
  83.  
  84. /* This function preserves a single file, and announces its success/failure
  85.  * via an e-mail message.
  86.  */
  87. void preserve(tname, when)
  88.     char    *tname;        /* name of a temp file to be preserved */
  89.     char    *when;        /* description of when the editor died */
  90. {
  91.     int    infd;        /* fd used for reading from the temp file */
  92.     FILE    *outfp;        /* fp used for writing to the recovery file */
  93.     FILE    *index;        /* fp used for appending to index file */
  94.     char    outname[100];    /* the name of the recovery file */
  95.     char    *user;        /* name of the owner of the temp file */
  96. #if AMIGA
  97.     char    *prsvdir;
  98. #endif
  99.     int    i;
  100.  
  101.     /* open the temp file */
  102.     infd = open(tname, O_RDONLY|O_BINARY);
  103.     if (infd < 0)
  104.     {
  105.         /* if we can't open the file, then we should assume that
  106.          * the filename contains wildcard characters that weren't
  107.          * expanded... and also assume that they weren't expanded
  108.          * because there are no files that need to be preserved.
  109.          * THEREFORE... we should silently ignore it.
  110.          * (Or loudly ignore it if the user was using -R)
  111.          */
  112.         if (rewrite_now)
  113.         {
  114.             perror(tname);
  115.         }
  116.         return;
  117.     }
  118.  
  119.     /* read the header and name from the file */
  120.     if (read(infd, hdr.c, BLKSIZE) != BLKSIZE
  121.      || read(infd, name.c, BLKSIZE) != BLKSIZE)
  122.     {
  123.         /* something wrong with the file - sorry */
  124.         fprintf(stderr, "%s: trucated header blocks\n", tname);
  125.         close(infd);
  126.         return;
  127.     }
  128.  
  129.     /* If the filename block contains an empty string, then Elvis was
  130.      * only keeping the temp file around because it contained some text
  131.      * that was needed for a named cut buffer.  The user doesn't care
  132.      * about that kind of temp file, so we should silently delete it.
  133.      */
  134.     if (name.c[0] == '\0' && name.c[1] == '\177')
  135.     {
  136.         close(infd);
  137.         unlink(tname);
  138.         return;
  139.     }
  140.  
  141.     if (rewrite_now)
  142.     {
  143.         /* we don't need to open the index file */
  144.         index = (FILE *)0;
  145.  
  146.         /* make sure we can read every block! */
  147.         for (i = 1; i < MAXBLKS && hdr.n[i]; i++)
  148.         {
  149.             lseek(infd, (long)hdr.n[i] * (long)BLKSIZE, 0);
  150.             if (read(infd, buf.c, BLKSIZE) != BLKSIZE)
  151.             {
  152.                 /* messed up header */
  153.                 fprintf(stderr, "%s: unrecoverable -- header trashed\n", name.c);
  154.                 close(infd);
  155.                 return;
  156.             }
  157.         }
  158.  
  159.         /* open the user's file for writing */
  160.         outfp = fopen(name.c, "w");
  161.         if (!outfp)
  162.         {
  163.             perror(name.c);
  164.             close(infd);
  165.             return;
  166.         }
  167.     }
  168.     else
  169.     {
  170.         /* open/create the index file */
  171.         index = fopen(PRSVINDEX, "a");
  172.         if (!index)
  173.         {
  174.             perror(PRSVINDEX);
  175.             exit(1);
  176.         }
  177.  
  178.         /* create the recovery file in the PRESVDIR directory */
  179. #if AMIGA
  180.         prsvdir = &PRSVDIR[strlen(PRSVDIR) - 1];
  181.         if (*prsvdir == '/' || *prsvdir == ':')
  182.         {
  183.             sprintf(outname, "%sp%ld", PRSVDIR, ftell(index));
  184.         }
  185.         else
  186. #endif
  187.         sprintf(outname, "%s%cp%ld", PRSVDIR, SLASH, ftell(index));
  188.         outfp = fopen(outname, "w");
  189.         if (!outfp)
  190.         {
  191.             perror(outname);
  192.             close(infd);
  193.             fclose(index);
  194.             return;
  195.         }
  196.     }
  197.  
  198.     /* write the text of the file out to the recovery file */
  199.     for (i = 1; i < MAXBLKS && hdr.n[i]; i++)
  200.     {
  201.         lseek(infd, (long)hdr.n[i] * (long)BLKSIZE, 0);
  202.         if (read(infd, buf.c, BLKSIZE) != BLKSIZE)
  203.         {
  204.             /* messed up header */
  205.             fprintf(stderr, "%s: unrecoverable -- header trashed\n", name.c);
  206.             fclose(outfp);
  207.             close(infd);
  208.             if (index)
  209.             {
  210.                 fclose(index);
  211.             }
  212.             unlink(outname);
  213.             return;
  214.         }
  215.         fputs(buf.c, outfp);
  216.     }
  217.  
  218.     /* add a line to the index file */
  219.     if (index)
  220.     {
  221.         fprintf(index, "%s %s\n", outname, name.c);
  222.     }
  223.  
  224.     /* close everything */
  225.     close(infd);
  226.     fclose(outfp);
  227.     if (index)
  228.     {
  229.         fclose(index);
  230.     }
  231.  
  232.     /* Are we doing this due to something more frightening than just
  233.      * a ":preserve" command?
  234.      */
  235.     if (*when)
  236.     {
  237.         /* send a mail message */
  238.         mail(ownername(tname), name.c, when);
  239.  
  240.         /* remove the temp file -- the editor has died already */
  241.         unlink(tname);
  242.     }
  243. }
  244.  
  245. main(argc, argv)
  246.     int    argc;
  247.     char    **argv;
  248. {
  249.     int    i;
  250.     char    *when = "the editor went away";
  251.  
  252. #if MSDOS || TOS
  253.     /* expand any wildcards in the command line */
  254.     argv = wildexpand(&argc, argv);
  255. #endif
  256.  
  257.     /* do we have a "when" argument? */
  258.     i = 1;
  259.     if (argc >= i + 1 && !strcmp(argv[i], "-R"))
  260.     {
  261.         rewrite_now = 1;
  262.         when = "";
  263.         i++;
  264. #if ANY_UNIX
  265.         setuid(geteuid());
  266. #endif
  267.     }
  268. #if OSK
  269.     else
  270.     {
  271.         setuid(0);
  272.     }
  273. #endif
  274.     if (argc >= i + 1 && argv[i][0] == '-')
  275.     {
  276.         when = argv[i] + 1;
  277.         i++;
  278.     }
  279.  
  280.     /* preserve everything we're supposed to */
  281.     while (i < argc)
  282.     {
  283.         preserve(argv[i], when);
  284.         i++;
  285.     }
  286. }
  287.